<template>
  <div
    class="table-container"
    :class="[mobileTable ? '' : 'h-100 no-scrollbar scroll-x']"
  >
    <!-- 搜索 -->
    <InputAddressSearch :modelValue="search" @search="inputSearch" />
    <!-- 表格数据展示 -->
    <table
      class="pc-table flex-1"
      v-if="data"
      :class="bindTableClass"
      ref="tableRef"
    >
      <thead>
        <tr>
          <td
            :style="bindColumnsStyle(column)"
            v-for="column in columns"
            :key="column.key"
          >
            {{ $t(column.title) }}
          </td>
          <td v-if="operate" class="operate thead">
            <slot name="header-operate">
              <template v-if="operate.consult">{{
                $t("btnText.consult")
              }}</template>
              <template v-else>
                {{ $t("tag.operate") }}
              </template>
            </slot>
          </td>
        </tr>
      </thead>
      <tbody :class="[hover ? 'hover' : '', striped ? 'striped' : '']">
        <template v-if="data && data.length > 0">
          <tr v-for="(row, rowIndex) in data" :key="rowIndex">
            <td
              :style="bindColumnsStyle(column)"
              v-for="(column, columnIndex) in columns"
              :key="column.key"
            >
              <slot
                :name="column.key"
                :row="row"
                :rowIndex="rowIndex"
                :columnIndex="columnIndex"
              >
                {{ row[column.key] }}
              </slot>
            </td>
            <td class="operate" v-if="operate">
              <slot name="operate" :row="row" :index="rowIndex">
                <div>
                  <span
                    v-if="operate.detail"
                    @click="onClickOperate(row, rowIndex, 'detail')"
                    >{{ $t("btnText.detail") }}</span
                  >
                  <span
                    v-if="operate.pay"
                    @click="onClickOperate(row, rowIndex, 'pay')"
                    >{{ $t("btnText.pay") }}</span
                  >
                  <IconConsult
                    @click="onClickOperate(row, rowIndex, 'consult')"
                  />
                </div>
              </slot>
            </td>
          </tr>
        </template>
      </tbody>
      <NoData v-if="data.length == 0" />
    </table>
    <template v-else>
      <div class="pc-skeleton">
        <Skeleton pc :rows="5" full />
      </div>
    </template>
    <div class="mobile-table">
      <AppTableCard
        @consult="mobileConsult"
        v-if="mobileTable == 'card'"
        :data="data"
      />
    </div>
    <!-- 分页 -->
    <ShowMore
      :currentPage="page"
      :totalCount="total"
      @change="paginationChange"
    ></ShowMore>
  </div>
</template>

<script setup lang="ts">
import {
  computed,
  getCurrentInstance,
  nextTick,
  onBeforeUnmount,
  onMounted,
  ref,
  watch,
} from "vue";
const $t = getCurrentInstance()?.appContext.config.globalProperties.$t;

type ColumnItem = {
  title: string;
  key: string;
  width?: string;
};

type Props = {
  // 表格数据
  data: any[];
  columns: ColumnItem[];
  // 绑定搜索
  search: string;
  // 绑定分页
  page?: number;
  total?: number;
  // 表头配置
  thead?: {
    // 表头背景色
    background?: string;
    // 操作表头文本
    operateText?: string;
  };
  // 操作
  operate?: {
    detail?: string | boolean;
    pay?: string | boolean;
    consult?: string | boolean;
  };
  // 搜索框提示文本
  placeholder?: string;
  // 行悬浮变色
  hover?: boolean;
  // 表格大小
  size?: "small" | "default";
  // 斑马色
  striped?: boolean;
  // 字体
  fontFamily?: string;
  // 主题
  theme?: "primary";
  // 分页
  pagination?: {};
  // 文本不换行
  noWrap?: boolean;
  // 边框
  border?: boolean;
  // 阴影
  shadow?: boolean;
  // 移动端显示表格形式
  mobileTable?: "card";
};

const props = withDefaults(defineProps<Props>(), {
  hover: false,
  size: "default",
  noWrap: true,
  border: true,
  shadow: true,
  theme: "primary",
  total: 0,
  columns: () => [],
});

const bindColumnsStyle = computed(() => {
  return (column: ColumnItem) => {
    let style = "";
    if (column.width) {
      style += `min-width:${column.width};flex: 0 1 auto;`;
    }
    return style;
  };
});

const bindTableClass = computed(() => {
  let classNameList: any[] = [];
  if (props.size) {
    classNameList.push(props.size);
  }
  if (props.theme) {
    classNameList.push(props.theme);
  }
  if (props.noWrap) {
    classNameList.push(props.noWrap ? "text-no-wrap" : "");
  }
  if (props.operate?.consult) {
    classNameList.push(props.operate.consult ? "consult" : "");
  }
  if (props.border) {
    classNameList.push(props.border ? "border" : "");
  }
  if (props.shadow) {
    classNameList.push(props.shadow ? "shadow" : "");
  }
  return classNameList.join(" ");
});

const emits = defineEmits([
  "update:page",
  "update:search",
  "click-operate",
  "search",
  "change",
]);
const onClickOperate = (row: any, index: number, type: string) => {
  emits("click-operate", { row, index, type });
};

// 加载完重置表格列宽
const tableRef = ref<HTMLElement | undefined>();
const resetTableColumnsWidth = () => {
  nextTick(() => {
    if (!tableRef.value && props.columns.length > 0) return;
    setTimeout(() => {
      nextTick(() => {
        const thead_tds = tableRef.value?.querySelectorAll("thead td");
        const tbody_trs = tableRef.value?.querySelectorAll("tbody tr");
        const maxWidths: number[] = [];
        thead_tds?.forEach((element: Element, index: number) => {
          maxWidths[index] = (
            element as HTMLElement
          ).getBoundingClientRect().width;
        });
        tbody_trs?.forEach((element: Element) => {
          element
            .querySelectorAll("td")
            .forEach((td: Element, index: number) => {
              (td as HTMLElement).style.width = maxWidths[index] + "px";
            });
        });
      });
    });
  });
};

// 搜索================================================
const inputSearch = (value: string) => {
  emits("update:search", value);
  emits("search", value);
};

// 分页================================================
const paginationChange = ({ page, pageSize }) => {
  emits("update:page", page);
  emits("change", page, pageSize);
};

onMounted(() => {
  resetTableColumnsWidth();
  window.addEventListener("resize", resetTableColumnsWidth);
});

// 移动端
const mobileConsult = ({ item, index, type }) => {
  onClickOperate(item, index, type);
};

onBeforeUnmount(() => {
  window.removeEventListener("resize", resetTableColumnsWidth);
});

watch([() => props.data, () => props.columns], () => {
  resetTableColumnsWidth();
});
</script>
<style scoped lang="less">
.table-container {
  display: flex;
  flex-direction: column;
}
table {
  font-size: 16px;
  width: 100%;
  white-space: normal;
  word-break: break-all;
  font-family: v-bind(fontFamily);
  td {
    align-self: stretch;
    padding: 12px;
    vertical-align: middle;
  }
  thead {
    background-color: v-bind(theadBgColor);
    color: #969696;
    tr {
      display: flex;
      td {
        flex: 1;
      }
    }
  }
  tbody {
    color: #323232;
    tr {
      display: flex;
      border-bottom: 1px solid #ebeff2;
      align-items: center;
      transition: all 0.15s ease-inout;

      td {
        display: flex;
        align-items: center;
        flex: 1;
        .operate {
          display: flex;
          gap: 40px;
          span {
            cursor: pointer;
            &:hover {
              color: #4168ff;
            }
          }
        }
      }
    }
  }

  td.operate {
    max-width: 240px;
    flex: 0 1 auto;
    min-width: 80px;
  }
}

table {
  tbody {
    &.striped {
      tr:nth-child(even) {
        background-color: #fcfdfd;
      }
    }
    // 表格悬浮变色
    &.hover {
      tr:hover {
        background-color: #ebeff2;
      }
    }
  }
  &.primary {
    thead {
      color: #fff;
      background-color: var(--yd-primary-color);
    }
    tbody {
      tr:nth-child(odd) {
        background-color: rgba(61, 136, 242, 0.3);
      }
      tr:nth-child(even) {
        background-color: rgba(61, 136, 242, 0.1);
      }
    }
  }
  &.small {
    thead tr td {
      padding: 13px 12px !important;
    }
    tbody tr td {
      padding: 11px 12px !important;
    }
  }
  &.text-no-wrap {
    thead {
      white-space: nowrap;
    }
  }
  &.consult {
    td.operate {
      display: flex;
      justify-content: center;
      align-items: center;
    }
  }
  &.border {
    tr {
      border: 0;
    }
    td {
      border-right: 1px solid #fff;
      &:last-child {
        border-right: none;
      }
    }
  }
  &.shadow {
    border: 1px solid lightgray;
    box-shadow: 0 0 0.20833vw rgba(0, 0, 0, 0.2);
  }
}

.mobile-table {
  display: none;
}
@media screen and (max-width: 768px) {
  .pc-table {
    display: none;
  }
  table {
    width: 300%;
    font-size: 72px;
    td {
      padding: 64px !important;
      flex: 1 !important;
    }
  }
  .mobile-table {
    display: block;
  }
}
</style>
